#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

void init_openssl_library(void) {
    SSL_library_init();
    SSL_load_error_strings();
    ERR_load_BIO_strings();
    OpenSSL_add_all_algorithms();
}

SSL_CTX* create_context(void) {
    const SSL_METHOD* method = SSLv23_server_method();  // 使用 SSLv23 方法，支持更多协议版本
    SSL_CTX* ctx = SSL_CTX_new(method);
    if (!ctx) {
        perror("Unable to create SSL context");
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }
    return ctx;
}

void configure_context(SSL_CTX* ctx) {
    // 设置服务器端证书和私钥
    if (SSL_CTX_use_certificate_file(ctx, "./cert/server.crt", SSL_FILETYPE_PEM) <= 0 ||
        SSL_CTX_use_PrivateKey_file(ctx, "./cert/private.key", SSL_FILETYPE_PEM) <= 0) {
        perror("Error setting certificate or private key");
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }
}

void handle_client(SSL* ssl) {
    // 在这里处理客户端连接
    // 在实际应用中，你可能需要在这里进行数据交换、业务逻辑等操作
    // 例如，你可以使用 SSL_read 和 SSL_write 函数进行数据传输

    const char* response = "Hello, SSL World!\n";
    SSL_write(ssl, response, strlen(response));

    // 关闭 SSL 连接
    SSL_shutdown(ssl);
    SSL_free(ssl);
}

int start_wossl() {
    init_openssl_library();

    SSL_CTX* ctx = create_context();
    configure_context(ctx);

    // 创建 TCP 套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("Unable to create socket");
        exit(EXIT_FAILURE);
    }

    // 绑定和监听

    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(443);  // 你可以使用其他端口

    if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("Unable to bind");
        exit(EXIT_FAILURE);
    }

    if (listen(sockfd, 5) < 0) {
        perror("Unable to listen");
        exit(EXIT_FAILURE);
    }

    while (1) {
        // 等待客户端连接
        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);
        int client_sockfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len);
        if (client_sockfd < 0) {
            perror("Unable to accept");
            exit(EXIT_FAILURE);
        }

        // 创建 SSL 对象
        SSL* ssl = SSL_new(ctx);
        SSL_set_fd(ssl, client_sockfd);

        // SSL 握手
        if (SSL_accept(ssl) <= 0) {
            perror("Error during SSL handshake");
            ERR_print_errors_fp(stderr);
        } else {
            // 处理客户端连接
            handle_client(ssl);
        }

        // 关闭客户端连接
        close(client_sockfd);
    }

    // 关闭 SSL 上下文
    SSL_CTX_free(ctx);

    return 0;
}
